import base64
import json
import pickle

from django.http import JsonResponse
from django.shortcuts import render

# Create your views here.
from django.views import View
from django_redis import get_redis_connection

from apps.goods.models import SKU

"""
1.  京东的网站，登录用户可以实现购物车，未登录用户也可以实现购物车     v
    淘宝必须登录
   
2.  登录用户数据保存在哪里？        服务器         mysql/redis
    未登录用户数据保存到哪里？       客户端         cookie
    
3. 保存哪些数据
    redis:
        user_id, sku_id,count,selected
    cookie:
        sku_id, count, selected
        
4. 数据组织
    redis：
        user_id, sku_id, count, selected
        
        hash
        user_id:
                sku_id:count
                xxx_sku_id:selected
        进一步优化！！！
        尽量少的占用内存
    cookie:
        {
        sku_id:{count:xxxx,selected:xxx},
        sku_id:{count:xxxx,selected:xxx},
        sku_id:{count:xxxx,selected:xxx},
        }
        
5. 
    cookie字典转换为字符串保存起来，数据没有加密
    
    base64
    
    字段 =========》 pickle二进制 ===============》 base64
    
"""


class CartsView(View):
    """
    前端: 我们点击添加购物车之后， 前端将商品id发送给后端
    后端:
        请求:     接收参数，验证参数
        业务逻辑:   根据商品id查询数据库看看商品id对不对
                  数据入库
                    登录用户如redis,
                        链接redis
                        获取用户id
                        hash
                        set
                        返回响应

                    未登录用户如cookie
                        现有cookie字典
                        字典转化为bytes
                        bytes类型数据base64编码
                        设置cookie
                        返回响应
        响应:     返回JSON

        路由: post /carts/
        步骤:
            1. 接收数据
            2. 验证数据
            3. 判断用户登录状态
            4. 登录用户保存redis
                4.1. 链接redis
                4.2. 操作hash
                4.3. 操作set
                4.4. 返回响应
            5. 未登录用户保存cookie
                5.1 先有cookie字典
                5.2 字典转化诶bytes
                5.3 bytes类型数据base64编码
                5.4 设置cookie
                5.5 返回响应

    """
    def post(self, request):
        # 1. 接收数据
        data = json.loads(request.body.decode())
        sku_id = data.get('sku_id')
        count = data.get('count')

        # 2. 验证数据
        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return JsonResponse({'code': 400, "errmsg": "查无此商品"})

        # 类型强制转换
        try:
            count = int(count)
        except Exception:
            count = 1

        # 3. 判断用户登录状态
        user = request.user

        if user.is_authenticated:
            # 4. 登录用户保存redis
            # 4.1. 链接redis
            redis_cli = get_redis_connection('carts')
            pipeline = redis_cli.pipeline()
            # 4.2. 操作hash
            # redis_cli.hset("carts_%s" % user.id, sku_id, count)
            # 进行累加操作
            pipeline.hincrby('carts_%s'%user.id, sku_id, count)

            # 4.3. 操作set
            pipeline.sadd('selected_%s' % user.id, sku_id)
            pipeline.execute()

            # 4.4. 返回响应
            return JsonResponse({'code':0, 'errmsg': 'ok'})

        else:
            # 5. 未登录用户保存cookie
            # 5.0 先读取cookie数据
            cookie_carts = request.COOKIES.get('carts')
            # b'\x80\x03}q\x00K\x10}q\x01(X\x05\x00\x00\x00countq\x02K\x01X\x08\x00\x00\x00selectedq\x03\x88us.'
            # b'gAN9cQBLEH1xAShYBQAAAGNvdW50cQJLAVgIAAAAc2VsZWN0ZWRxA4h1cy4='
            # gAN9cQBLEH1xAShYBQAAAGNvdW50cQJLAVgIAAAAc2VsZWN0ZWRxA4h1cy4=
            if cookie_carts:
                print(cookie_carts)
                print(base64.b64decode(cookie_carts))
                print(pickle.loads(base64.b64decode(cookie_carts)))
                carts = pickle.loads(base64.b64decode(cookie_carts))
            else:
                # 5.1 先有cookie字典
                carts = {}

            if sku_id in carts:
                original_count = carts[sku_id]['count']
                count += original_count

            #     carts[sku_id] = {'count': count, 'selected': True}
            # else:
            carts[sku_id] = {'count': count, 'selected': True}
            # 5.2 字典转化诶bytes
            carts_bytes = pickle.dumps(carts)
            print(carts_bytes)
            # 5.3 bytes类型数据base64编码
            carts_base64_encode = base64.b64encode(carts_bytes)
            print(carts_base64_encode)
            # 5.4 设置cookie
            response = JsonResponse({'code': 0, 'errmsg': 'ok'})
            response.set_cookie('carts', carts_base64_encode.decode(), max_age=3600*24*12)
            print(carts_base64_encode.decode())
            # 5.5 返回响应
            return response

    """
    # 1. 判断用户是否登录
    # 2. 登录用户查询redis
    #     2.1 链接redis
    #     2.2 hash
    #     2.3 set
    #     2.4 遍历判断
    #     
    # 3. 未登录用户查询cookie
    #     3.1 读取cookie
    #     3.2 判断是否存在购物车数据
    #         如果存在就解码，
    #         如果不存在就初始化字典
    # 4 根据商品id查询商品信息
    # 5 将对象数据转换为字典数据
    # 6 返回响应   
    """
    def get(self, request):
        # 1. 判断用户是否登录
        user = request.user
        if user.is_authenticated:

            # 2. 登录用户查询redis
            # 2.1 链接redis
            redis_cli = get_redis_connection('carts')

            # 2.2 hash
            sku_id_counts = redis_cli.hgetall('carts_%s' % user.id)
            # 2.3 set
            selected_ids = redis_cli.smembers('selected_%s' % user.id)
            # 2.4 将redis数据转化为和cookie一样 方便后续操作
            carts = {}
            for sku_id, count in sku_id_counts.items():
                carts[int(sku_id)] = {
                    'count': int(count),
                    'selected': sku_id in selected_ids
                }

        else:
            # 3. 未登录用户查询cookie
            # 3.1 读取cookie
            carts = request.COOKIES.get('carts')
            # 3.2 判断是否存在购物车数据
            if carts is not None:
                # 会有bug不知道咋回事
                # 如果存在就解码，
                carts = pickle.loads(base64.b64decode(carts))
            else:
                # 如果不存在就初始化字典
                carts = {}

        # 4 根据商品id查询商品信息
        sku_ids = carts.keys()

        skus = SKU.objects.filter(id__in=sku_ids)

        # 5 将对象数据转换为字典数据
        sku_list = []
        for sku in skus:
            sku_list.append({
                'id': sku.id,
                'price': sku.price,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'selected': carts[sku.id]['selected'],
                'count': carts[sku.id]['count'],
                'amount': sku.price*(carts[sku.id]['count'])
            })

        # 6 返回响应
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'cart_skus': sku_list})

    """
    # 1. 获取用户信息
    # 2. 接收数据
    # 3. 验证数据
    # 4. 登录用户更新redis
    #     4.1 链接redis
    #     4.2 hash
    #     4.3 set
    #     4.4 返回响应
    # 5. 未登录用户更新cookie
    #     5.1 先读取购物车数据，
    #         判断有没有
    #         如果没有则解密数据
    #         如果没有则初始化一个空字典
    #     5.2 更新数据
    #     5.3 重新对字典进行编码和base64加密
    #     5.4 设置cookie
    #     5.5 返回响应
    
    """
    def put(self, request):
        # 1. 获取用户信息
        user = request.user
        # 2. 接收数据
        data = json.loads(request.body.decode())
        sku_id = data.get('sku_id')
        count = data.get('count')
        selected = data.get('selected')

        # 3. 验证数据
        if not all([sku_id, count]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全'})

        try:
            SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return JsonResponse({'code': 400, 'errmsg': '没有此商品'})

        try:
            count = int(count)
        except Exception:
            count = 1

        if user.is_authenticated:
            # 4. 登录用户更新redis
            #     4.1 链接redis
            redis_cli = get_redis_connection('carts')
            #     4.2 hash
            redis_cli.hset('carts_%s' % user.id, sku_id, count)
            #     4.3 set
            if selected:
                redis_cli.sadd('selected_%s' % user.id, sku_id)
            else:
                redis_cli.srem('selected_%s' % user.id, sku_id)
            #     4.4 返回响应
            return JsonResponse({'code': 0, 'errmsg': 'ok', 'cart_sku': {'count': count, 'selected': selected}})

        else:
            # 5. 未登录用户更新cookie
            #     5.1 先读取购物车数据，
            cookie_cart = request.COOKIES.get('carts')
            #         判断有没有
            if cookie_cart is not None:
                # 如果没有则解密数据
                carts = pickle.loads(base64.b64decode(cookie_cart))
            else:
                # 如果没有则初始化一个空字典
                carts = {}

            #     5.2 更新数据
            if sku_id in carts:
                carts[sku_id] = {
                    'count': count,
                    'selected': selected
                }
            #     5.3 重新对字典进行编码和base64加密
            carts_encode = base64.b64encode(pickle.dumps(carts))

            #     5.4 设置cookie
            response = JsonResponse({'code': 0, 'errmsg': 'ok', 'cart_sku': {'count': count, 'selected': selected}})
            response.set_cookie('carts', carts_encode, max_age=14*24*3600)
            #     5.5 返回响应
            return response

    """
    # 1. 接收请求
    # 2. 验证参数
    # 3. 根据用户状态
    # 4. 登录用户操作redis
    #     4.1 链接redis
    #     4.2 hash
    #     4.3 set
    #     4.4 返回响应
    # 5. 未登录用户操作cookie
    #     5.1 读取cookie中的购物车数据
    #         判断数据是否存在
    #         存在则解码
    #         不存在则初始化字典
    #     5.2 删除数据
    #     5.3 我们需要对字典数据进行编码和base64处理
    #     5.4 设置cookie
    #     5.5 返回响应
    
    """
    def delete(self, request):
        # 1. 接收请求
        data = json.loads(request.body.decode())
        # 2. 验证参数
        sku_id = data.get('sku_id')
        try:
            SKU.objects.get(pk = sku_id)
        except SKU.DoesNotExist:
            return JsonResponse({"code": 400, "errmsg": "没有此商品"})
        # 3. 根据用户状态
        user = request.user
        if user.is_authenticated:
            # 4. 登录用户操作redis
            #     4.1 链接redis
            redis_cli = get_redis_connection('carts')
            #     4.2 hash
            redis_cli.hdel('carts_%s' % user.id, sku_id)
            #     4.3 set
            redis_cli.srem('selected_%s' % user.id, sku_id)
            #     4.4 返回响应
            return JsonResponse({'code':0, 'errmsg': "ok"})

        else:
            # 5. 未登录用户操作cookie
            #     5.1 读取cookie中的购物车数据
            cookie_cart = request.COOKIES.get('carts')
            # 判断数据是否存在
            if cookie_cart is not None:
                # 存在则解码
                carts = pickle.loads(base64.b64decode(cookie_cart))
                # 不存在则初始化字典
            else:
                carts = {}
            # 5.2 删除数据
            del carts[sku_id]
            # 5.3 我们需要对字典数据进行编码和base64处理
            new_carts = base64.b64encode(pickle.dumps(carts))
            # 5.4 设置cookie
            response = JsonResponse({'code':0, 'errmsg': "ok"})
            response.set_cookie('carts', new_carts.decode(), max_age=14*24*3600)
            # 5.5 返回响应
            return response





